<?php
/**
 * 提货产品
 * (model)
 */
namespace App\Models\Shipping;

use App\Models\Inventory\PublicCn;
use App\Models\Product\ProductClassify;
use App\Models\Basics\SysArea;
use App\Models\Product\ProductSku;
use App\Models\SsBasic\AreaSku;
use App\Models\SsBasic\AreaSkuAvg;
use App\Models\SsBasic\AreaSkuEstimate;
use App\Models\SsBasic\AreaSkuStock;
use App\Util\RExcel;
use App\Util\User;
use Illuminate\Database\Eloquent\Model;
class SSku extends Model
{
    protected $table = 's_shipping_sku';

    protected $guarded = [];

    public static $_status = [
        1 => '未申请',
        2 => '待审批',
        3 => '驳回',
        4 => '通过',
    ];

    public static $_isLock = [
        0 => '未锁定',
        1 => '已锁定',
    ];

    /**
     * 备货站点sku
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function area_sku(){
        return $this->belongsTo(AreaSku::class,'area_psku','area_psku');
    }

    /**
     * 备货sku预估
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function estimate(){
        return $this->hasOne(AreaSkuEstimate::class,'area_psku','area_psku');
    }

    public function area(){
        return $this->belongsTo(SysArea::class,'area_id');
    }

    public function sku(){
        return $this->belongsTo(ProductSku::class,'psku_id');
    }

    public function skuClassify(){
        return $this->hasOneThrough(
            ProductClassify::class,
            ProductSku::class,
            'id',//中间表
            'id',//目标表
            'psku_id',//当前模型
            'classify_id'//中间表
        );
    }

    public function _avg(){
        return $this->hasOne(AreaSkuAvg::class,'area_psku','area_psku');
    }

    public function stock(){
        return $this->hasOne(AreaSkuStock::class,'area_psku','area_psku');
    }

    /**
     * 所有库存(含公共库存)-国内在途
     * 获取当前提货库存系数
     * @param $model
     * @param $publicCn
     * @return float|int|string
     */
    public static function getShippingCurrentFactor($model,$publicCn){
        $inventory = self::getShippingInventory($model);
        $inventory += $publicCn;
        $estimate = AreaSkuEstimate::getEstimate($model->estimate);
        return AreaSkuEstimate::getInventoryFactor($inventory,$estimate);
    }

    /**
     * 提货系数 库存 没有国内在途
     * @param $model
     * @return mixed
     */
    public static function getShippingInventory($model){
        return ($model->stock->fba_instant_num ?? 0) + ($model->stock->fba_transit_num ?? 0) +
            ($model->stock->cn_instant_num ?? 0) +
            ($model->stock->os_instant_num ?? 0) + ($model->stock->os_transit_num ?? 0);
    }

    /**
     * 所有库存(含公共库存)-国内在途+总需求
     * 提货系数
     * @param $model
     * @param $publicCn
     * @param $applyNumTotal
     * @return float|int|string
     */
    public static function getShippingFactor($model,$publicCn,$applyNumTotal){
        $inventory = self::getShippingInventory($model);
        $inventory += $publicCn;
        $inventory += $applyNumTotal;
        $estimate = AreaSkuEstimate::getEstimate($model->estimate);
        return AreaSkuEstimate::getInventoryFactor($inventory,$estimate);
    }

    /**
     * 数据导出
     * @param $query
     * @param $shippingDate
     */
    public static function exeDownload($query,$shippingDate){
        $head1 = ['品类','站点','SKU','季节性','产品名称',
            '3天AVG','7天AVG','15天AVG','30天AVG','AVG',
            'FBA在库','FBA在途', '公共在库','国内在库','国内在途', '海外仓在库','海外仓在途',
            '生产周期','空运时效','海运时效','空运提货库存安全系数','海运提货库存安全系数','提货库存目前系数'];
        $head2 = [];
        foreach ($shippingDate as $label){
            $head2[] = $label.'需求';
        }
        $head3 = ['差值','状态','提货员'];
        $head = array_merge($head1,$head2,$head3);
        RExcel::exportCsv('提货产品',function () use ($head, $query,$shippingDate) {
            $fp = fopen('php://output', 'w');
            fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));
            fputcsv($fp, $head);
            $query->chunk(1000, function ($re) use ($fp,$shippingDate){
                $data = self::_getDownloadData($re,$shippingDate);
                foreach ($data as $item) {
                    fputcsv($fp, $item);
                }
            });
        });
    }

    private static function _getDownloadData($res,$shippingDate)
    {
        $seller = [];
        foreach ($res as $model){
            $sellerId = $model->seller_id ?: 0;
            if(!array_key_exists($sellerId,$seller)){
                $seller[$sellerId] = User::getUsernameById($sellerId);
            }
            $publicCn = PublicCn::getInstant($model->psku_id);
            $data1 = [
                $model->skuClassify->title ?? '',
                $model->area->area ?? '',
                $model->sku->psku_code ?? '',
                ProductClassify::$_season[$model->skuClassify->season ?? 3],
                $model->sku->psku_cn ?? '',
                $model->_avg->avg3 ?? 0,
                $model->_avg->avg7 ?? 0,
                $model->_avg->avg15 ?? 0,
                $model->_avg->avg30 ?? 0,
                $model->_avg->avg ?? 0,
                $model->stock->fba_instant_num ?? 0,
                $model->stock->fba_transit_num ?? 0,
                $publicCn,
                $model->stock->cn_instant_num ?? 0,
                $model->stock->cn_transit_num ?? 0,
                $model->stock->os_instant_num ?? 0,
                $model->stock->os_transit_num ?? 0,
                $model->purchase_cycle ?: 0,
                $model->air_day ?: 0,
                $model->sea_day ?: 0,
                $model->air_factor,
                $model->sea_factor,
                self::getShippingCurrentFactor($model,$publicCn)];
            $data2 = [];
            $applyNum = SSkuApply::getApplyNum($model->area_id,$model->psku_id,array_key_first($shippingDate),array_key_last($shippingDate));
            $applyNumTotal = 0;
            foreach ($shippingDate as $date => $label){
                $apply = array_key_exists($date,$applyNum) ? $applyNum[$date] : 0;
                $data2[] = $apply;
                $applyNumTotal += $apply;
            }
            $data3 = [
                ($model->stock->cn_transit_num ?? 0) - $applyNumTotal,
                self::$_status[$model->status],
                $seller[$sellerId],
            ];
            $temp = array_merge($data1,$data2,$data3);
            yield $temp;
        }
    }
}
